package cn.tyz.kotlin.note

import android.provider.Telephony.Carriers.PASSWORD

/**
 * @author : tyz
 * @ClassName: Note01
 * @Description:
 * @time 2018/5/22 22:55
 */
private const val USERNAME = "kk" //用户名
private const val PASSWORD = "123456" //密码
private const val ADMIN_USER = "admin" //管理员用户名
private const val ADMIN_PASSWORD = "admin" //管理员密码
private const val USER = 0 //用户模式
private const val DEBUG = 1 //调试模式

const val FINAL_HELLO_WORLD: String = "HelloWorld" //编译期常量
class Note02 {

    fun main(args: Array<String>) {
        showDemo16(args)
    }


//    分支表达式
    fun showDemo16(args: Array<String>){
        //当args参数非空且第0个参数为1时进入DEBUG模式，不然进入USER模式
        val mode = if (args.isNotEmpty() && args[0] == "1") { DEBUG } else { USER }

        println("请输入用户名：")
        val username = readLine() //读取用户输入信息
        println("请输入密码：")
        val password = readLine() //读取用户输入信息

        if (mode == DEBUG && username == ADMIN_USER && password == ADMIN_PASSWORD) { //模式为调试模式，且登陆的是管理员
            println("管理员登陆成功")
        } else if (username == USERNAME && password == PASSWORD) { //调试模式为空，且登陆的是普通用户
            println("登陆成功")
        } else {
            println("登陆失败")
        }
    }

    /** 17变长参数
     * 变长参数的长度是可变的，相当于数组，使用vararg关键词表示，
     * 在函数的参数中，若变长参数不是最后一个，
     * 在调用该函数的时候，非变长参数的参数需使用具名参数，
     * 也就是要明确指定其他参数的名称
     */
    fun showVarArgs(){
        hello(3.0, 1, 2, 3, 4, string = "Great") //参数string需明确指定参数名

        val array = intArrayOf(6,7,8,9)
        hello(4.0, *array, string = "never") //用*号将array数组传给变长参数，变长参数只支持array，不支持list
    }
    fun hello(num: Double, vararg ints: Int, string: String) {
        ints.forEach(::println)
    }

    /**18常量与变量
     * 运行时常量是编译时并不知道其值，真正运行的时候才获取
     * 编译期常量是编译时候就知道其值的常量
     * kotlin中val并不是编译期常量，可通过反射的方式修改值，要将其转成编译期常量需要加上const关键词，可提高运行效率
     *     var 变量
           val //常量
     */


    //19
    fun showTry(args: Array<String>){
        //用try...catch...为一个数赋值
        val result = try {
                        args[0].toInt() / args[1].toInt()
                    } catch (e: Exception) {
                        e.printStackTrace()
                        0
                    }
        println(result)
        println("3 / 4 = ${add2(3, 4)}")
    }

    fun add2(x: Int, y: Int): Int {
        return  try {
                    x / y
                } catch (e: Exception) {
                    0
                } finally {
                    println("end")
                }
    }

   /**
    * 22 类成员
    * 属性：类范围内的常量或变量
    * 方法：类范围内的函数
    * kotlin自动为类的变量设置getter和setter，类中成员变量的默认访问权限是public
    * 属性初始化
    * 1.属性的初始化尽量在构造方法中完成
    * 2.无法在构造方法中初始化，尝试降级为局部变量
    * 3.var用lateinit延迟初始化，val用by lazy
    * 4.可空类型谨慎用null直接初始化
    * */
   fun showObj(){
       val a = A()
       println(a.e)

       a.d = "haha"
       println(a.d)
   }
   class A {
       var b = 0
       var c = 0
           get() {
               println("尝试获取变量b的值")
               return field //field是变量c的默认值，getter和setter中才能访问到
           }
           protected set(value) { //单独给setter设置访问权限
               println("尝试设置变量b的值")
               field = value
           }

       /*
       类中的变量必须马上赋值，一开始不想指定值的话，
       需加lateinit关键字，但加了之后若是在初始化之前就使用会报错的，
       lateinit只能用在var上
        */
       lateinit var d: String

       val e: X by lazy { //val常量延迟加载
           println("init X")
           X()
       }
   }

    class X

    //23迭代列表
    fun showIterator(){
        val list = MyIntList()
        list.add(1)
        list.add(2)
        list.add(3)
        for (i in list) {
            println(i)
        }
    }
    class MyIterator(val iterator: Iterator<Int>){ //自定义迭代器
        operator fun next(): Int { //下一个
            return iterator.next()
        }

        operator fun hasNext(): Boolean { //判断是否有下一个
            return iterator.hasNext()
        }
    }

    class MyIntList { //自定义列表
        private val list = ArrayList<Int>()

        fun add(int: Int) { //添加到列表
            list.add(int)
        }

        fun remove(int: Int) { //从列表中移除
            list.remove(int)
        }

        operator fun iterator(): MyIterator { //迭代列表
            return MyIterator(list.iterator())
        }
    }
}